package org.zjvis.datascience.common.dto;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Joiner;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.zjvis.datascience.common.constant.SqlTemplate;
import org.zjvis.datascience.common.util.DozerUtil;
import org.zjvis.datascience.common.util.ToolUtil;
import org.zjvis.datascience.common.vo.OperatorTemplateVO;

import java.util.ArrayList;
import java.util.List;

/**
 * @description 自定义算子模板信息表，自定义算子模板DTO
 * @date 2021-04-27
 */
@Data
public class OperatorTemplateDTO extends BaseDTO {
    private final String BODY_TAIL = "if __name__ == '__main__':\n" +
            "    ret = %s\n" +
            "    return ret\n" +
            "    \n" +
            "$BODY$\n" +
            "  LANGUAGE plpythonu VOLATILE\n" +
            "  COST 100";

    private final String BODY_HEADER = "CREATE OR REPLACE FUNCTION %s(%s) \n" +
            "    RETURNS \"pg_catalog\".\"text\" AS $BODY$";

    private Long id;
    private String name;
    private Long userId;
    private Integer type;
    private Integer subType;
    private String subTypeName;
    private String description;
    private String functionName;
    private String inputParams;
    private String outputParams;
    private String languageType;
    private String scriptBody;
    private String sdk;
    private String notebookId;
    private String interpreter;
    private String fullScript;
    private int isExport;

    /**
     * 状态 0-待审核  1-已通过  2-已驳回  3-已失效
     */
    private Integer status;

    /**
     * 审核意见
     */
    private String suggestion;

    public OperatorTemplateVO view() {
        OperatorTemplateVO vo = DozerUtil.mapper(this, OperatorTemplateVO.class);
        if (StringUtils.isNotEmpty(inputParams)) {
            vo.setInputParamsObj(JSONObject.parseObject(inputParams));
        }
        if (StringUtils.isNotEmpty(outputParams)) {
            vo.setOutputParamsObj(JSONObject.parseObject(outputParams));
        }
        return vo;
    }

    /**
     * 补充脚本头部和尾部信息
     *
     * @return
     */
    public String supplementScript() {
        OperatorTemplateVO vo = this.view();
        JSONObject inputObj = vo.getInputParamsObj();
        JSONObject outputObj = vo.getOutputParamsObj();
        StringBuilder sb = new StringBuilder();
        String header = "";
        String tail = "";
        if (StringUtils.isEmpty(inputObj.getString("script_head"))) {
            long timeStamp = System.currentTimeMillis();
            functionName = String.format("\"%s\".\"define_func_%s\"", SqlTemplate.SCHEMA, timeStamp);
            JSONArray input = inputObj.getJSONArray("input");
            List<String> params = new ArrayList<>();
            for (int i = 0; i < input.size(); ++i) {
                JSONObject item = input.getJSONObject(i);
                String name = item.getString("name");
                String paramType = item.getString("paramType");
                params.add(String.format("\"%s\" %s", name, paramType));
            }
            header = String.format(BODY_HEADER, functionName, Joiner.on(", ").join(params));
            inputObj.put("script_head", header);
        } else {
            header = inputObj.getString("script_head");
        }
        if (StringUtils.isEmpty(outputObj.getString("script_tail"))) {
            String entryFunction = ToolUtil.extractEntryFunction(scriptBody);
            tail = String.format(BODY_TAIL, entryFunction);
            outputObj.put("script_tail", tail);
        } else {
            tail = outputObj.getString("script_tail");
        }
        sb.append(String.format("%s\n", header));
        sb.append(scriptBody);
        sb.append(String.format("\n%s\n", tail));
        this.setInputParams(inputObj.toJSONString());
        this.setOutputParams(outputObj.toJSONString());
        return sb.toString();
    }

}
